package com.chiyoyo.multipay.framework.core.client.dto.refund;

import com.chiyoyo.multipay.framework.core.client.exception.PayException;
import com.chiyoyo.multipay.framework.core.enums.refund.PayRefundStatusRespEnum;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.time.LocalDateTime;

/**
 * @author chil
 * 渠道退款订单 Response DTO
 */
@Getter
@Setter
@Accessors(chain = true)
public class PayRefundRespDTO {

    /**
     * 退款状态
     * 枚举 {@link PayRefundStatusRespEnum}
     */
    private Integer status;

    /**
     * 外部退款号
     * 对应 PayRefundDO 的 no 字段
     */
    private String outRefundNo;

    /**
     * 渠道退款单号
     * 对应 PayRefundDO.channelRefundNo 字段
     */
    private String channelRefundNo;

    /**
     * 退款成功时间
     */
    private LocalDateTime successTime;

    /**
     * 原始的异步通知结果
     */
    private Object rawData;

    /**
     * 调用渠道的错误码
     * 注意：这里返回的是业务异常，而是不系统异常。
     * 如果是系统异常，则会抛出 {@link PayException}
     */
    private String channelErrorCode;
    /**
     * 调用渠道报错时，错误信息
     */
    private String channelErrorMsg;

    private PayRefundRespDTO() {
    }

    /**
     * 创建一个表示退款状态为【WAITING】的退款返回对象
     *
     * @param channelRefundNo 渠道退款编号
     * @param outRefundNo     商户退款编号
     * @param rawData         原始数据，可以为任意类型
     * @return 返回一个包含退款响应信息的PayRefundRespDTO对象，其退款状态为【WAITING】
     */
    public static PayRefundRespDTO waitingOf(String channelRefundNo,
                                             String outRefundNo, Object rawData) {
        PayRefundRespDTO respDTO = new PayRefundRespDTO();
        respDTO.status = PayRefundStatusRespEnum.WAITING.getStatus();
        respDTO.channelRefundNo = channelRefundNo;
        // 相对通用的字段
        respDTO.outRefundNo = outRefundNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

    /**
     * 创建一个表示退款状态为【SUCCESS】的退款返回对象
     *
     * @param channelRefundNo 渠道退款编号
     * @param successTime     退款成功时间
     * @param outRefundNo     商户退款编号
     * @param rawData         原始数据，可以为任意类型
     * @return 返回一个包含退款响应信息的PayRefundRespDTO对象，其退款状态为【SUCCESS】
     */
    public static PayRefundRespDTO successOf(String channelRefundNo, LocalDateTime successTime,
                                             String outRefundNo, Object rawData) {
        PayRefundRespDTO respDTO = new PayRefundRespDTO();
        respDTO.status = PayRefundStatusRespEnum.SUCCESS.getStatus();
        respDTO.channelRefundNo = channelRefundNo;
        respDTO.successTime = successTime;
        // 相对通用的字段
        respDTO.outRefundNo = outRefundNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

    /**
     * 创建一个表示退款状态为【FAILURE】的退款返回对象
     *
     * @param outRefundNo 商户退款编号
     * @param rawData     原始数据，可以为任意类型
     * @return 返回一个包含退款响应信息的PayRefundRespDTO对象，其退款状态为【FAILURE】
     */
    public static PayRefundRespDTO failureOf(String outRefundNo, Object rawData) {
        return failureOf(null, null,
                outRefundNo, rawData);
    }

    /**
     * 创建一个表示退款状态为【FAILURE】的退款返回对象
     *
     * @param channelErrorCode 渠道错误码，表示退款失败的原因
     * @param channelErrorMsg  渠道错误消息，描述退款失败的具体信息
     * @param outRefundNo      商户退款编号
     * @param rawData          原始数据，可以为任意类型
     * @return 返回一个包含退款响应信息的PayRefundRespDTO对象，其退款状态为【FAILURE】
     */
    public static PayRefundRespDTO failureOf(String channelErrorCode, String channelErrorMsg,
                                             String outRefundNo, Object rawData) {
        PayRefundRespDTO respDTO = new PayRefundRespDTO();
        respDTO.status = PayRefundStatusRespEnum.FAILURE.getStatus();
        respDTO.channelErrorCode = channelErrorCode;
        respDTO.channelErrorMsg = channelErrorMsg;
        // 相对通用的字段
        respDTO.outRefundNo = outRefundNo;
        respDTO.rawData = rawData;
        return respDTO;
    }
}
